#Include ../../_lib/GdipStarter.ahk
#Include ../../_lib/Cursor.ahk

#Include debugView.ahk
#Include data.ahk


class Render {

  static penSize := 2, penColor := 0xff00B7E4

  __New(tool, target) {
    this.tool := tool, this.target := target
    this.brush := Gdip_BrushCreateSolid(0xFFffffff)
    this.curPenColor := 0xff79A16A
    target.GetPos(&x, &y, &w, &h)
    this.x := x, this.y := y, this.w := w, this.h := h
    this.canvas := Gui('+AlwaysOnTop +ToolWindow -Caption +E0x00080000 +Owner' target.hwnd)
    ShowGui(this.canvas, x, y, w, h)
    Hotkey('MButton', (*) => this.Move(), 'On')
  }

  EndDraw() {
    this.Draw(DrawData.d)
    hdc_frame := DllCall('GetDC', 'ptr', 0) ; TODO: 从canvas中获取
    hdd_frame := DllCall('GetDC', 'ptr', this.target.Hwnd)

    DllCall("BitBlt"
      , 'ptr', hdd_frame, 'int', -1, 'int', -1, 'int', w, 'int', h
      , 'ptr', hdc_frame, 'int', x, 'int', y
      , 'UInt', 0xCC0020)
    DllCall('ReleaseDC', 'int', 0, 'ptr', hdc_frame)
    DllCall('ReleaseDC', 'int', 0, 'ptr', hdd_frame)

    this.canvas.Destroy()
    HotKeysOff('Mbutton')
    Gdip_DeleteBrush(this.brush)
  }

  Move() {
    
  }

  undo(*) {
    DrawData.pop()
    this.Draw(DrawData.d)
  }

  RenderLine() => this._render(DrawType.LINE)
  RenderRect() => this._render(DrawType.RECT)
  RenderRectSolid() => this._render(DrawType.RECT_SOLID)

  _drawBase(G, w, h, data) {
    pen := Gdip_CreatePen(this.curPenColor, 1)
    Gdip_DrawRectangle(G, pen, 0, 0, w - 1, h - 1)
    Gdip_DeletePen(pen)

    for v in data {
      switch v.type {
        case DrawType.LINE:
          _pen := Gdip_CreatePen(v.color, v.penW)
          Gdip_DrawLine(G, _pen, v.coord*)
          Gdip_DeletePen(_pen)
        case DrawType.RECT:
          _pen := Gdip_CreatePen(v.color, v.penW)
          Gdip_DrawRectangle(G, _pen, v.coord*)
          Gdip_DeletePen(_pen)
        case DrawType.RECT_SOLID:
          _brush := Gdip_BrushCreateSolid(v.color)
          Gdip_FillRectangle(G, _brush, v.coord*)
          Gdip_DeleteBrush(_brush)
      }
    }
  }

  Draw(drawDataArr) {
    w := this.w, h := this.h
    hbm := CreateDIBSection(w, h)
    hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
    G := Gdip_GraphicsFromHDC(hdc), b := 1
    this._drawBase(G, w, h, drawDataArr)
    UpdateLayeredWindow(this.canvas.Hwnd, hdc, x, y, w, h)
    Gdip_DeleteGraphics(G)
    SelectObject(hdc, obm), DeleteObject(obm), DeleteDC(hdc)
  }


  _render(type) {
    initCursor := A_Cursor, canvas := this.canvas, state := DrawState.END
    ix := 0, iy := 0, fx := 0, fy := 0, coords := ''
    x := this.x, y := this.y, w := this.w, h := this.h
    Cursor.SetIcon(Cursor.Icon.cross)
    Hotkey('LButton', handleDraw, 'On')

    handleDraw(*) {
      switch state {
        case DrawState.END: start()
        case DrawState.DRAWING: end()
      }
    }

    start(*) {
      MouseGetPos(&mx, &my)
      ix := mx - x, iy := my - y, state := DrawState.DRAWING
      SetTimer _, 10
    }

    end(*) {
      SetTimer _, 0
      MouseGetPos(&mx, &my)
      Hotkey('LButton', 'off')
      if type & DrawType.RECT_SOLID {
        coords.push(Render.penColor)
      } else {
        coords.push(Render.penColor, Render.penSize)
      }
      state := DrawState.END
      DrawData.putByType(type, coords*)
      Cursor.SetIcon(initCursor)
    }

    _(*) {
      MouseGetPos(&mx, &my)
      mx -= x, my -= y
      if mx = fx && my = fy
        return
      hbm := CreateDIBSection(w, h)
      hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
      G := Gdip_GraphicsFromHDC(hdc), b := 1

      this._drawBase(G, w, h, DrawData.d)
      switch type {
        case DrawType.LINE:
          drawLine(G, ix, iy, mx, my)
          coords := [ix, iy, mx, my]
        case DrawType.RECT, DrawType.RECT_SOLID:
          _w := mx - ix, _h := my - iy
          _x := _w < 0 ? ix + mx - ix : ix, _y := _h < 0 ? iy + _h : iy
          _w := Abs(_w), _h := Abs(_h)
          drawRect(G, _x, _y, _w, _h, type & DrawType.RECT)
          coords := [_x, _y, _w, _h]
      }

      fx := mx, fy := my
      UpdateLayeredWindow(canvas.Hwnd, hdc, x, y, w, h)
      Gdip_DeleteGraphics(G)
      SelectObject(hdc, obm), DeleteObject(obm), DeleteDC(hdc)

      D.setT Format('x1:{} y1:{}`nx2:{} y2:{}', x, y, mx, my)
    }

    drawLine(G, x1, y1, x2, y2) {
      pen := Gdip_CreatePen(this.curPenColor, Render.penSize)
      Gdip_DrawLine(G, pen, x1, y1, x2, y2)
      Gdip_DeletePen(pen)
    }

    drawRect(G, x, y, w, h, solid) {
      pen := Gdip_CreatePen(this.curPenColor, Render.penSize)
      solid ? Gdip_DrawRectangle(G, pen, x, y, w, h) : Gdip_FillRectangle(G, this.brush, x, y, w, h)
      Gdip_DeletePen(pen)
    }

  }
}